/**
 * This program is free software but WITHOUT ANY WARRANTY OR CONDITIONS OF ANY KIND.
 *
 * Copyright (C) 2008-2013 www.pretty-tools.com
 */

var gUserProfile = new Array();
var gSaveRules = false;

var gRuleTree;
var gRuleTreeContentView = {
    rowCount: 0,
    selection: {
        count: 0
    },
    getTreeChildren: function () {
        return document.getElementById("rules_treechildren");
    },
    getItemAtIndex: function (idx) {
        return this.getTreeChildren().childNodes[idx];
    },
    isContainer: function (idx) {
        return this.getItemAtIndex(idx).getAttribute("page_idx") == null;
    },
    getParent: function (idx) {
        var elem = this.getItemAtIndex(idx);
        var domain = elem.getAttribute("domain_idx");
        for (var sibling = elem; sibling; sibling = sibling.previousSibling)
        {
            if (sibling.getAttribute("page_idx") == null && domain == elem.getAttribute("domain_idx"))
                return sibling;
        }
        return null;
    },
    findRowIndex : function(elem)
    {
        var elems = this.getTreeChildren().childNodes;
        for (var i = 0, numOfElems = elems.length; i < numOfElems; ++i)
            if (elems[i].id == elem.id)
                return i;
        return -1;
    },
    getParentIndex: function (idx) {
        return this.findRowIndex(this.getParent(idx));
    },
    getIndexOfItem: function(treeitem) {
        return this.findRowIndex(treeitem);
    },
    setCellText: function (idx, column, text) {
        var row = this.getItemAtIndex(idx);
        row.childNodes[column].innerHTML = "<NOBR>" + text + "</NOBR>";
    },
    remove: function (elemToRemove) {
        if (!elemToRemove)
            return;
        if (elemToRemove.className == "treeSelectedRow")
        {
            gRuleTree.currentIndex = -1;
            this.selection.count = 0;
        }

        elemToRemove.parentNode.removeChild(elemToRemove);
        --this.rowCount;
    },
    col_domain: 0,
    col_page_pattern: 1,
    col_element_pattern: 2
};
var gRuleTreeView = gRuleTreeContentView;

function initRuleTree()
{
    try
    {
        // init global data
        gRuleTree = document.getElementById("rules_tree");
        gRuleTree.currentIndex = -1;
    }
    catch(ex)
    {
        if (gLogger.enabled) gLogger.error("initRuleTree: ", ex);
    }
}

function createDomainElements(idx, domain)
{
    var treecell = document.createElement("TD");
    treecell.colSpan = 3;
    treecell.innerHTML = "<NOBR>" + domain + "</NOBR>";

    var domainItem = document.createElement("TR");
    domainItem.className = "treeRow";
    domainItem.setAttribute("id", "domain_"+idx);
    domainItem.setAttribute("container", "true");
    domainItem.setAttribute("open", "true");
    domainItem.setAttribute("domain_idx", idx);
    domainItem.appendChild(treecell);

    return domainItem;
}

function getPagePatternLabel(page)
{
    return page.pattern.source;
}

function getElementPatternLabel(page)
{
    return page.elementTag + ": " + page.elementPattern.source;
}

function createPageElements(domainIndex, pageIndex, page)
{
    var treeitem = document.createElement("TR");
    if (page.disabled || !page.supported)
        treeitem.className = "treeDisabledRow";
    else
        treeitem.className = "treeRow";
    treeitem.setAttribute("id", "domain_"+domainIndex+"_page_"+pageIndex);
    treeitem.setAttribute("domain_idx", domainIndex);
    treeitem.setAttribute("page_idx", pageIndex);

    var treecell;
    // empty cell
    treeitem.appendChild(document.createElement("TD"))
    // page pattern
    treeitem.appendChild(treecell = document.createElement("TD"))
    treecell.innerHTML = "<NOBR>" + getPagePatternLabel(page) + "</NOBR>";
    // element pattern
    treeitem.appendChild(treecell = document.createElement("TD"))
    treecell.innerHTML = "<NOBR>" + getElementPatternLabel(page) + "</NOBR>";

    return treeitem;
}

function createRuleElements(idx, item, rules_treechildren)
{
    if (!rules_treechildren)
        rules_treechildren = document.getElementById("rules_treechildren");

    var domainTreeRow = createDomainElements(idx, item.domain);
    rules_treechildren.appendChild(domainTreeRow);
    ++gRuleTreeView.rowCount;

    for (var p in item.pages)
    {
        var page = item.pages[p];
        if (!page) // skip null
            continue;

        rules_treechildren.appendChild(createPageElements(idx, p, page));
        ++gRuleTreeView.rowCount;
    }
}

function appendRuleElements(idx, treeitem)
{
    var domain = document.getElementById("domain_"+idx);

    var sibling = domain;
    while (sibling = sibling.nextSibling)
    {
        if (sibling.getAttribute("domain_idx") != domain.getAttribute("domain_idx"))
            break;
    }

    if (sibling)
        domain.parentNode.insertBefore(treeitem, sibling);
    else
        domain.parentNode.appendChild(treeitem);
    ++gRuleTreeView.rowCount;
}

function updateUserRules()
{
    try
    {
        var rules_treechildren = document.getElementById("rules_treechildren");
        // remove old
        while (rules_treechildren.hasChildNodes())
        {
            rules_treechildren.removeChild(rules_treechildren.childNodes[0]);
        }
        gRuleTreeView.rowCount = 0;

        for (var i in gUserProfile)
        {
            createRuleElements(i, gUserProfile[i], rules_treechildren);
        }

        updateButtons();
    }
    catch(ex)
    {
        if (gLogger.enabled) gLogger.error("updateUserRules: ", ex);
    }
}

function getTreeCurrentIndexOrFail()
{
    var idx = gRuleTree.currentIndex;
    if (idx >= 0 && idx < gRuleTreeView.rowCount)
        return idx;

    throw "Invalid index";
}

function countPages(pages)
{
    if (!pages || !pages.length)
        return 0;

    var count = 0;
    for (var p in pages)
    {
        if (pages[p]) // skip null
            ++count;
    }
    return count;
}

function findDomainIndex(domain)
{
    for (var i in gUserProfile)
    {
        if (gUserProfile[i] && gUserProfile[i].domain == domain)
            return i;
    }

    if (gLogger.enabled) gLogger.debug("findDomainIndex: Domain not found " + domain);
    return -1;
}

function isSingleRuleInDomain(idx)
{
    try
    {
        var treeitem = gRuleTreeContentView.getItemAtIndex(idx);
        if (!yrprxBrowser.hasAttribute(treeitem, "domain_idx"))
            throw "Invalid item.";

        return countPages(gUserProfile[1*treeitem.getAttribute("domain_idx")].pages) <= 1;
    }
    catch(ex)
    {
        if (gLogger.enabled) gLogger.error("isSingleRuleInDomain: ", ex);
    }
    return true;
}

function selectTreeNode(idx)
{
    var childNodes = document.getElementById("rules_treechildren").childNodes;
    if (idx < 0 || idx >= childNodes.length)
        return;

    if (gRuleTree.currentIndex != -1)
    {
        var prevSelected = childNodes[gRuleTree.currentIndex];
        prevSelected.className = prevSelected.getAttribute("prevClassName");
    }

    gRuleTree.currentIndex = idx;
    gRuleTreeView.selection.count = 1;
    var newSelected = childNodes[idx];

    newSelected.setAttribute("prevClassName", newSelected.className);
    newSelected.className = "treeSelectedRow";

    var tree_container = document.getElementById("tree_container");
    var offsetTop = newSelected.offsetTop-childNodes[0].offsetTop;
    if (offsetTop < tree_container.scrollTop)
        tree_container.scrollTop = offsetTop;
    else
    {
        var offsetBottom = newSelected.offsetTop + newSelected.clientHeight;
        if (offsetBottom > (tree_container.scrollTop + tree_container.clientHeight))
            tree_container.scrollTop = offsetBottom - tree_container.clientHeight;
    }
}

function updateRow(idx, page)
{
    gRuleTreeView.setCellText(idx, gRuleTreeView.col_page_pattern, getPagePatternLabel(page));
    gRuleTreeView.setCellText(idx, gRuleTreeView.col_element_pattern, getElementPatternLabel(page));

    var treeitem = gRuleTreeContentView.getItemAtIndex(idx);
    if (treeitem.className == "treeSelectedRow")
    {
        if (page.disabled || !page.supported)
            treeitem.setAttribute("prevClassName", "treeDisabledRow");
        else
            treeitem.setAttribute("prevClassName", "treeRow");
    }
    else
    {
        if (page.disabled || !page.supported)
            treeitem.className = "treeDisabledRow";
        else
            treeitem.className = "treeRow";
    }
}

function updateDomain(idx, domain)
{
    gRuleTreeView.setCellText(idx, gRuleTreeView.col_domain, domain);
}

function removeRule()
{
    try
    {
        //TODO: think about confirmation... (add 'force' parameter if confirmation)

        var idx = getTreeCurrentIndexOrFail();

        var treeitem = gRuleTreeContentView.getItemAtIndex(idx);
        if (!yrprxBrowser.hasAttribute(treeitem, "domain_idx"))
            throw "Invalid item. no 'domain_idx' attribute";

        var sDomainIndex = treeitem.getAttribute("domain_idx")
        var domainIndex = 1*sDomainIndex;
        if (gRuleTreeView.isContainer(idx))
        {
            if (gLogger.enabled) gLogger.debug("removeRule: Remove all rules for domain idx = " + domainIndex);

            gUserProfile[domainIndex] = null;
            for (var sibling = treeitem; sibling; )
            {
                if (sibling.getAttribute("domain_idx") != sDomainIndex)
                    break;

                var elemToRemove = sibling;
                sibling = sibling.nextSibling;

                gRuleTreeView.remove(elemToRemove);
            }
        }
        else
        {
            if (!yrprxBrowser.hasAttribute(treeitem, "page_idx"))
                throw "Invalid item. no 'page_idx' attribute";

            var pageIndex = 1*treeitem.getAttribute("page_idx");
            if (gLogger.enabled) gLogger.debug("removeRule: Remove rules idx = " + pageIndex);

            gUserProfile[domainIndex].pages[pageIndex] = null;
            gUserProfile[domainIndex].checksum = null;
            // check rules count now
            if (countPages(gUserProfile[domainIndex].pages) == 0)
            {
                // remove parent
                gUserProfile[domainIndex] = null; // reset domain
                // remove parent
                gRuleTreeView.remove(gRuleTreeView.getParent(idx));
            }

            gRuleTreeView.remove(treeitem);
        }
        gSaveRules = true;

        if (gRuleTreeView.rowCount > 0) selectTreeNode(idx > 0 ? idx-1 : 0);

        updateButtons();
    }
    catch(ex)
    {
        if (gLogger.enabled) gLogger.error("removeRule: ", ex);
    }
}

function isFirstRule(treeitem)
{
    return !treeitem.previousSibling || treeitem.previousSibling.getAttribute("page_idx") == null;
}

function isLastRule(treeitem)
{
    return !treeitem.nextSibling || treeitem.nextSibling.getAttribute("page_idx") == null;
}
